/*
 * 文件名： WechatWcpayCmbcManager.java
 * 
 * 工程名称: bis-manager
 *
 * Gopay
 *
 * 创建日期： 2017年5月15日
 *
 * Copyright(C) 2017, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.manager.bank.wcpay;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import com.gopay.common.cipher.utils.LoggerMaskUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.CmbcConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.WcPayBaseMessage;
import com.gopay.common.domain.bank.wechat.wcpay.cmbc.MsgHead;
import com.gopay.common.domain.bank.wechat.wcpay.cmbc.PayMsgBody;
import com.gopay.common.domain.bank.wechat.wcpay.cmbc.QueryMsgBody;
import com.gopay.common.domain.bank.wechat.wcpay.cmbc.RefundMsgBody;
import com.gopay.common.domain.bank.wechat.wcpay.cmbc.TransMsg;
import com.gopay.common.domain.cust.CustSettledConfigInfo;
import com.gopay.common.domain.cust.CustSettledInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.user.dao.CustSettledConfigInfoDao;
import com.gopay.common.user.dao.CustSettledInfoDao;
import com.gopay.remote.bank.businesses.WcPayService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 微信公众号支付/支付宝服务窗民生银行通道报文拼装处理
 *
 * @author 宣广海
 *
 * @version 
 *
 * @since 2017年5月15日
 */
public class WcpayCmbcManager {
	private static Logger logger = LoggerFactory.getLogger(WcpayCmbcManager.class);
	/**
	 * 注入对象
	 */
	@Resource(name = "wechatWcPayConfig")
	private Map<String, String> wechatWcPayConfig;

	@Resource(name = "wcPayCmbcServiceClient")
	private WcPayService wcPayCmbcServiceClient;
	
	@Resource(name = "custSettledInfoDao")
	private CustSettledInfoDao custSettledInfoDao;
	@Resource(name = "custSettledConfigInfoDao")
    private CustSettledConfigInfoDao custSettledConfigInfoDao;
	
	/**
	 * 
	 * 功能描述：微信公众号支付/支付宝服务窗民生渠道支付报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年5月15日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object payment(BaseMessage msg) throws GopayException {
		TransMsg<PayMsgBody> message = new TransMsg<PayMsgBody>();
		msg.setBankOrderId(modifyOrderId(msg.getOrderId()));
		try {
			BeanUtils.copyProperties(msg, message);
			/**
			 * 获取商户入驻编号
			 */
			CustSettledInfo info =null;
			if(BankConstants.BANK_LOGO_WECHAT.equals(msg.getOutStlmCd())){
				info= custSettledInfoDao.getCustSettledInfo(msg.getCustomerID(),
						CmbcConstants.WECHAT_SETTLED, CmbcConstants.WECHAT_SETTLED_SUCCESS);
			}	
			if(BankConstants.BANK_LOGO_ALIPAY.equals(msg.getOutStlmCd())){
				info= custSettledInfoDao.getCustSettledInfo(msg.getCustomerID(),
						CmbcConstants.ZFB_SETTLED, CmbcConstants.ZFB_SETTLED_SUCCESS);
			}	
			if (null == info) {
				logger.info(msg.getCustomerID() + ",此商户没有找到民生入驻帐号！");
				throw new GopayException(ProcCodeConstants.PROC_CODE_100E1165);
			}
			/**
			 * 准备构建报文体对象
			 */
			WcPayBaseMessage wcPayMsg=(WcPayBaseMessage)msg;
			
			PayMsgBody payMsgBody = new PayMsgBody();
			payMsgBody.setMerchantCode(info.getBankMerchantCode());
			/**
			 * 金额精确到元，保留2位小数
			 */
			payMsgBody.setTotalAmount(wcPayMsg.getAmount());
			payMsgBody.setSubject(wcPayMsg.getGoodsBody());
			payMsgBody.setDesc(wcPayMsg.getGoodsBody());
			payMsgBody.setOperatorId("");
			payMsgBody.setStoreId("01");
			payMsgBody.setTerminalId("");
			// 1-限定不能使用信用卡支付
			payMsgBody.setLimitPay(wcPayMsg.getLimitCreditPay());
						
			//商户微信公众号
			if(BankConstants.BANK_LOGO_WECHAT.equals(msg.getOutStlmCd())){
				String appId=wcPayMsg.getAppId();
				if(StringUtils.isBlank(appId)){
					//从后台绑定处获取商户已经绑定的APPID
					List<CustSettledConfigInfo> list=custSettledConfigInfoDao.findSettledConfigInfo(msg.getCustomerID(), "2");
					if(list!=null &&list.size()>0){
						CustSettledConfigInfo custSettledConfigInfo=list.get(0);
						//appId="wxa22cf3b4098c2f4a";
						appId=custSettledConfigInfo.getBusinessValue();
						logger.info("微信 appid="+appId);
						
					}					
				}
				payMsgBody.setSubAppid(appId);
			}		
			payMsgBody.setUserId(wcPayMsg.getSubOpenId());
			payMsgBody.setSource("");
			payMsgBody.setGoodsTag("");
			/**
			 * 订单失效时间目前是6分钟后失效
			 * 指定订单的支付有效时间（分钟数），超过有效时间用户将无法支付。若不指定该参数则系统默认设置24小时支付有效时间。参数允许设置范围：
			 * 1-1440区间的整数值，超过1440默认设置1440
			 */
			payMsgBody.setExpireTime(6);
			
			message.setMsgHead(creatHead());
			message.setMsgBody(payMsgBody);
			message.setPlainMessage(buildSignPlain(message));
			logger.info(msg.getOutStlmCd()+ " wcpay CMBC pay manager sign message :" + LoggerMaskUtils.maskString(buildSignPlain(message)));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7025, e);
		}
		return	wcPayCmbcServiceClient.payment(message);
	}
	/**
	 * 
	 * 功能描述：微信公众号支付民生渠道订单查询报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年5月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object orderQuery(BaseMessage msg) throws GopayException {
		TransMsg<QueryMsgBody> message = new TransMsg<QueryMsgBody>();		
		try {
			BeanUtils.copyProperties(msg, message);	
			/**
			 * 准备构建报文体对象
			 */
			QueryMsgBody queryBody = new QueryMsgBody();		
			//原订单号
			queryBody.setOriReqMsgId(msg.getBankOrderId());	
			queryBody.setOperatorId("");
			message.setMsgHead(creatHead());
			message.setMsgBody(queryBody);
			message.setPlainMessage(buildSignPlain(message));
			logger.info("wcpay query manager orderQuery message :" + buildSignPlain(message));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6063, e);
		}
		return	wcPayCmbcServiceClient.queryOrder(message);
	}
	/**
	 * 
	 * 功能描述：微信公众号支付民生渠道退款报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年5月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object refund(BaseMessage msg) throws GopayException {
		TransMsg<RefundMsgBody> message = new TransMsg<RefundMsgBody>();
		msg.setBankOrderId(modifyOrderId(msg.getOrderId()));
		try {
			BeanUtils.copyProperties(msg, message);
			/**
			 * 准备构建报文体对象
			 */
			RefundMsgBody refundBody = new RefundMsgBody();
			/**
			 * 原支付交易流水号
			 */
			refundBody.setOriReqMsgId(msg.getTkOriBankOrderId());
			/**
			 * 退款金额精确到元，保留2位小数
			 */
			refundBody.setRefundAmount(msg.getAmount());
			refundBody.setRefundReason("");
			refundBody.setOperatorId("");
			refundBody.setStoreId("");
			refundBody.setTerminalId("");
			
			message.setMsgHead(creatHead());
			message.setMsgBody(refundBody);
			message.setPlainMessage(buildSignPlain(message));
			logger.info("wcpay refund manager sign message :" + buildSignPlain(message));
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1163, e);
		}
		return	wcPayCmbcServiceClient.refund(message);
	}
	/**
	 * 
	 * 功能描述：微信公众号支付民生渠道异步通知验签报文
	 *
	 * @param msg
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年5月16日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object verify(BaseMessage msg) throws GopayException {
		boolean falg = false;
		try {
			logger.info("wcpay manager verify message :" + ToStringBuilder.reflectionToString(msg));
			falg = (boolean) wcPayCmbcServiceClient.verify(msg);
		} catch (Exception e) {
			logger.info(e.getMessage());
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026, e);
		}
		return falg;
	}
	private static String modifyOrderId(String orderId) {
		return "MS" + orderId.substring(2);
	}
	public MsgHead creatHead() {
		MsgHead head = new MsgHead();
		head.setVersion(wechatWcPayConfig.get("WECHAT.WCPAY.CMBC.VERSION"));
		head.setMsgType(wechatWcPayConfig.get("WECHAT.WCPAY.CMBC.MESSAGETYPE"));
		head.setReqDate(new DateTime().toString("yyyyMMddHHmmss"));
		return head;
	}
	public String buildSignPlain(Object obj) {
		// 去掉多一个下划线的问题
		XStream xstream = new XStream(new DomDriver("UTF-8", new NoNameCoder()));
		xstream.processAnnotations(obj.getClass());
		xstream.aliasSystemAttribute(null, "class"); 
		return xstream.toXML(obj);
	}
}
